﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using AdaptiveAgents.Games;
using AdaptiveAgents.Agents;

namespace AdaptiveAgents.Running_Tools
{
    /// <summary>
    /// This class puts data in the "DataRow" unit.
    /// </summary>
    class DataRowProcessor
    {
        /// <summary>
        /// "DataRow" unit.
        /// </summary>
        private static DataRow dr;



        /// <summary>
        /// This function create "DataRow" unit.
        /// </summary>
        /// <param name="dt">"DataTable" unit</param>
        /// <returns>New "DataRow" unit</returns>
        public static DataRow createDataRow(DataTable dt)
        {
            dr = dt.NewRow();
            return dr;
        }



        /// <summary>
        /// This function put the game number to "DataRow" unit.
        /// </summary>
        /// <param name="number">Number of the game</param>
        public static void insertGamesNumber(int number)
        {
            dr["Game_Number"] = number;
        }



        /// <summary>
        /// This function put the epsilons data to "DataRow" unit.
        /// </summary>
        /// <param name="epsilonData">AgentsTypeList of epsilons</param>
        /// <param name="agents">Number of agents</param>
        public static void insertEpsilonsData(List<double> epsilonData, int agents)
        {
            for (int j = 0; j < agents; j++)
            {
                dr["Epsilon_" + j] = epsilonData[j];
            }
        }



        /// <summary>
        /// This function put the competence data to "DataRow" unit.
        /// </summary>
        /// <param name="competenceData">AgentsTypeList of competences</param>
        /// <param name="agents">Number of agents</param>
        public static void insertCompetenceData(List<double> competenceData, int agents)
        {
            for (int j = 0; j < agents; j++)
            {
                dr["Competence_" + j] = competenceData[j];
            }
        }



        /// <summary>
        /// This function put the average score to "DataRow" unit.
        /// </summary>
        /// <param name="score">The average score</param>
        public static void insertAverageScore(double score)
        {
            dr["Average_Score"] = score;
        }



        /// <summary>
        /// This function put the sum score to "DataRow" unit.
        /// </summary>
        /// <param name="game">"MDPGame" unit</param>
        public static void insertSumScore(MDPGame game)
        {
            dr["Sum_Score"] = game.GetAccumUtility();
        }



        /// <summary>
        /// This function put the MAX\MIN score to "DataRow" unit.
        /// </summary>
        /// <param name="rounds"></param>
        public static void insertMinMaxScore(int rounds)
        {
            // MAX\MIN utility
            double min, max;
            int i = 0;
            string tempString = null;
            double tempDouble = 0;

            tempString = (string)dr["Round_Utility_" + i];
            min = Convert.ToDouble(tempString);
            max = Convert.ToDouble(tempString);

            for (i = 1; i < rounds; ++i)
            {
                tempString = (string)dr["Round_Utility_" + i];
                tempDouble = Convert.ToDouble(tempString);

                if (tempDouble > max)
                {
                    max = tempDouble;
                }
                if (tempDouble < min)
                {
                    min = tempDouble;
                }
            }

            dr["Min_Score"] = min;
            dr["Max_Score"] = max;
        }



        /// <summary>
        /// This function put the utility round to "DataRow" unit.
        /// </summary>
        /// <param name="round">Round number</param>
        /// <param name="utility">Utility score</param>
        public static void insertRoundUtility(int round, double utility)
        {
            dr["Round_Utility_" + round.ToString()] = utility;
        }



        /// <summary>
        /// This function put the Average score to "DataRow" unit.
        /// </summary>
        /// <param name="env">"Environment" unit</param>
        /// <param name="rounds">Number of rounds</param>
        public static void insertAverageScorePerAgent(Environment env, int rounds)
        {
            List<Agent> list = env.agents;
            Agent agent = null;
            int id = 0;
            int actions = 0;
            double totalUtility = 0;
            double averageUtility = 0;

            for (int i = 0; i < list.Count; ++i)
            {
                agent = list[i];
                actions = agent.NumActions;
                id = agent.ID;
                ObservationsSet set = agent.getObservationByID(id, rounds);

                for (int j = 0; j < actions; ++j)
                {
                    totalUtility = totalUtility + set.get(j).Value;
                }

                averageUtility = totalUtility / actions;

                dr["Total_Score_Agent_" + i] = totalUtility;
                dr["Number_Actions_Agent_" + i] = actions;
                dr["Average_Score_Agent_" + i] = averageUtility;

                totalUtility = 0;
                
            }
            
        }
    }
}
